package com.ihealthway.all.groupbuy.services;

import com.ihealthway.all.utils.Utils;
import com.ihealthway.all.groupbuy.vo.OrderInfo;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Order info service
 *
 * @author 凡梦星尘(elkan1788@gmail.com)
 */
@IocBean(fields = {"dao"})
public class OrderInfoService extends BaseService<OrderInfo> {

    private static final Log logger = Logs.get();

    @Inject
    private PropertiesProxy conf;

    public List<OrderInfo> getOrderInfoForFront(Integer userId) {
        List<OrderInfo> orderInfoList = new ArrayList<>();
        String sqlStmt = "SELECT ord.*,gd.goods_name AS gdName,gd.price AS gdPrice,gd.sales AS gdSales,img.img_url AS imgUrl FROM gb_order_info AS ord " +
                "LEFT JOIN gb_goods AS gd ON gd.goods_id = ord.goods_id " +
                "LEFT JOIN (SELECT MIN(img_url) AS img_url,goods_id FROM gb_images_library " +
                "WHERE goods_id IS NOT NULL GROUP BY goods_id) AS img ON img.goods_id = ord.goods_id $condition";
        Sql sql = Sqls.create(sqlStmt);
        Pager pager = dao().createPager(1,30);
        sql.setPager(pager);
        sql.setCondition(Cnd.where("ord.u_id", "=", userId));
        sql.setCallback(new OrderInfoCallBack());
        dao().execute(sql);
        orderInfoList.addAll(sql.getList(OrderInfo.class));
        return orderInfoList;
    }

    public boolean checkOrderList(Integer goodsId, Integer userId) {

        Criteria cri = Cnd.cri();
        cri.where().andEquals("goods_id", goodsId);
        cri.where().andEquals("u_id", userId);
        // 3 Means not pay after expire
        cri.where().andNotEquals("data_status", "3");
        try {
            List<OrderInfo> orderInfoList = dao().query(OrderInfo.class, cri);
            if (orderInfoList!=null && !orderInfoList.isEmpty()) {
                return true;
            }
        } catch (Exception e) {
            logger.error("Check user order list fail!!!", e);
        }

        return false;
    }

    public String buildOrder(OrderInfo orderInfo) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String orderNo = dateFormat.format(new Date())+ Utils.buildRandom(4);
        orderInfo.setOrderId(orderNo);
        orderInfo.setCreateTime(new Date());
        orderInfo.setDataStatus("1");
        if (Strings.isNotBlank(orderInfo.getUserAgent())) {
            Pattern iphoneRegex = Pattern.compile("iPhone\\s+OS\\s+([\\d\\_]+)", Pattern.CASE_INSENSITIVE);
            Pattern androidRegex = Pattern.compile("Android\\s+([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
            Pattern verRegex = Pattern.compile("MicroMessenger\\/([\\d\\.]+)", Pattern.CASE_INSENSITIVE);
            Pattern netRegex = Pattern.compile("NetType\\/[0-9a-zA-Z+]*", Pattern.CASE_INSENSITIVE);

            String ua = orderInfo.getUserAgent();

            Matcher iphoneMcr = iphoneRegex.matcher(ua);
            Matcher androidMcr = androidRegex.matcher(ua);
            orderInfo.setMobileOS("Unknown");
            if (iphoneMcr.find()) {
                orderInfo.setMobileOS(iphoneMcr.group().split("")[0]);
            } else if (androidMcr.find()) {
                orderInfo.setMobileOS(androidMcr.group().split(" ")[0]);
            }

            Matcher verMcr = verRegex.matcher(ua);
            if (verMcr.find()) {
                orderInfo.setAppVersion(verMcr.group().split("/")[1]);
            }

            Matcher netMcr = netRegex.matcher(ua);
            if (netMcr.find()) {
                orderInfo.setNetworkType(netMcr.group().split("/")[1]);
            }
        }

        try {
            OrderInfo orderInfoTmp = dao().insert(orderInfo);
            orderNo = (orderInfoTmp == null ? null : orderNo);
        } catch (Exception e) {
            logger.error("Build new order info fail!!!", e);
            orderNo = null;
        }
        return orderNo;
    }

    public String updateOrderStatus(OrderInfo orderInfo) {
        String orderNo = orderInfo.getOrderId();
        try {
            int rows = dao().updateIgnoreNull(orderInfo);
            if (rows < 0) {
                orderNo = null;
            }
        } catch (Exception e) {
            logger.error("Update order info status fail!!!", e);
            orderNo = null;
        }
        return orderNo;
    }

    public boolean refundOrderPay(String orderIds) {
        boolean flag = false;
        Sql sql = Sqls.create("UPDATE gb_order_info SET data_status='5' WHERE data_status='4' AND order_id IN("+orderIds+")");
        try {
            dao().execute(sql);
            flag = false;
        } catch (Exception e) {
            logger.error("Update refund order pay fail!!!", e);
        }
        return flag;
    }

    public Map<String, Object> getDataList(Integer row, Integer page, String orderId, Integer companyId,
                                           String orderStat, String sDate, String eDate) {
        String sqlStmt = "SELECT " +
                "ord.*,gd.goods_name AS gdName,gd.price AS gdPrice,gd.sales AS gdSales,img.img_url AS imgUrl,cmy.c_name AS cName, ui.real_name AS realName " +
                "FROM gb_order_info AS ord " +
                "LEFT JOIN gb_goods AS gd ON gd.goods_id = ord.goods_id " +
                "LEFT JOIN (SELECT MIN(img_url) AS img_url,goods_id FROM gb_images_library WHERE goods_id IS NOT NULL GROUP BY goods_id) AS img ON img.goods_id = ord.goods_id " +
                "LEFT JOIN gb_company AS cmy ON cmy.c_id = ord.c_id " +
                "LEFT JOIN gb_user_info AS ui ON ui.u_id = ord.u_id  $condition";

        Criteria cri = Cnd.cri();
        if (Strings.isNotBlank(orderId)) {
            cri.where().andEquals("ord.order_id", orderId);
        }
        if (companyId!=null && companyId.intValue()>0) {
            cri.where().andEquals("ord.c_id", companyId);
        }
        if (Strings.isNotBlank(orderStat)) {
            cri.where().andEquals("ord.data_status", orderStat);
        }
        if (Strings.isNotBlank(sDate) && Strings.isNotBlank(eDate)) {
            cri.where().andBetween("ord.create_time", sDate, eDate);
        }

        Map<String, Object> result = easyuiDGPagerWithFetch(sqlStmt, page, row, cri,new OrderInfoCallBack());

        return result;
    }

    private class OrderInfoCallBack implements SqlCallback {

        @Override
        public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
            List<OrderInfo> orderList = new ArrayList<>();
            String sqlStmt = sql.getSourceSql();
            while (rs.next()) {
                OrderInfo orderInfo = getEntity().getObject(rs, null, "ord.");
                orderInfo.setGoodsName(rs.getString("gdName"));
                orderInfo.setGoodsPrice(rs.getInt("gdPrice"));
                orderInfo.setGoodsImgUrl(rs.getString("imgUrl"));
                orderInfo.setGoodsSales(rs.getInt("gdSales"));
                if (sqlStmt.indexOf("cName") > -1) {
                    orderInfo.setCompanyName(rs.getString("cName"));
                    orderInfo.setUserName(rs.getString("realName"));
                }
                if (Strings.isNotBlank(orderInfo.getBankType())) {
                    orderInfo.setBankType(conf.get(orderInfo.getBankType(), "未知来源"));
                }
                if (Strings.isNotBlank(orderInfo.getResultCode())) {
                    orderInfo.setResultCode(conf.get(orderInfo.getResultCode(), "未知"));
                }
                orderList.add(orderInfo);
            }
            return orderList;
        }
    }
}
